//ScoreCalculate.cpp
#include <iostream>
#include <cstdio>
#include <iomanip>
#include <windows.h>
#include <cstring>
#include "ScoreCalculate.h"
//include all extern cpp files 
#include "Check.cpp"	
using namespace std;
int main(void){
	int Subject,i;			//Vary i is set for circulate
	PromptInit();
	ErrorPromptInit();
	WarningPromptInit();	//Prompt For Console User-Interaction Interface Initialize
	cout<<prompt[0]<<endl<<endl;	//Head of the Application(The first line)
	cout<<DataTemplate[0]<<endl;	//
	cout<<"Template:"<<endl;
	cout<<DataTemplate[1]<<endl<<DataTemplate[2]<<endl<<endl;
	cout<<prompt[1];
//Invalid Input Warning Handling Procedure
//Have SOME MISTAKE:WHEN BEGIN WITH NUMBER,THE PROCEDURE COLLAPSE	
	char* buf=new char[20];
	bool InBuf;	
	do{
	cin>>buf;
		InBuf=true;
		for(i=0;i<strlen(buf);i++){
			if(buf[i]>0x39||buf[i]<0x30){
				InBuf=false;
			}
		}
		if(InBuf){
		Subject=atoi(buf);
		}else{
		SetWerrColour(ERR);
		cout<<"[Error]Invaild Input";
		SetColour((int)YEL,(int)Default.BackColour);
		cout<<"At least 1 character Input Detected\n"; 
		SetWerrColour(DFT);
		cout<<prompt[1];
		}
	}while(!InBuf);
	delete [] buf;//Dynamic Memory Assignment
	//Transform ASCII character to interger number; atoi() Function originally contained in file cstdlib
	SumScr=0.0;				//SumScr Initialize Procedure
	GPACal=0.0;
	struct ScoreData StuScr[Subject];
	SetColour((int)Default.FrontColour,(int)Default.BackColour);	
//Below Are Data-Input Procedure
	for(i=0;i<Subject;i++){
		StuScr[i].DataInit(); 
		cout<<"Line"<<i+1<<" --- ";
		//cin>>StuScr[i].SubjectName;
		scanf("%s",&(StuScr[i].SubjectName));
//Error Data Handle
//Comment:Infinite Change Logic 
		int* CAT=new int;	//Dynamic Memory Assignment
		int LN;		
//New Structure of Code For Infinity Change	
		if(stricmp(StuScr[i].SubjectName,"change")==0||stricmp(StuScr[i].SubjectName,"cng")==0){
		char* buf=new char[50];
		gets(buf);		//Input-Check for the Input-Buffer
			if(buf[0]!=' '){
			//Trigger The change/cng Werror Handle Procedure	
				do{//This do-while realizing the infinity-change data function 
					if(stricmp(StuScr[i].SubjectName,"cng")==0){  
					Display.FrontColour=GRN;
					SetColour(Display.FrontColour,Default.BackColour);
					cout<<"[Question] "<<"KeyWord Conflict"<<"  ";
					SetColour(Default.FrontColour,Default.BackColour); 
					cout<<"Do you want to Change the data?(Y/N)";//cng Question Prompt Handle
					//
					char* q=new char;
					cin>>*q;
					//Another Possible Version
						while(*q!='Y' && *q!='y'){//if *q=='Y' or *q=='y',skip all this warning handle procedure
							if(*q=='n'||*q=='N'){break;}
							Display.BackColour=YEL;
							Display.FrontColour=PUR;
							SetColour((int)Display.FrontColour,(int)Display.BackColour);
							cout<<"[Warning] "<<"Invaild Command"<<"  ";
							SetColour((int)Default.FrontColour,(int)Default.BackColour);
							cout<<"You Have ENTERED Invalid Command,Please enter the command again."<<endl;
							cout<<"Do you want to Change the data?(Y/N)";
							//Warning Handle(Prompt) Procedure
						cin>>*q;//New Yes/No Data Input 
						}
						if(*q=='n'||*q=='N'){
					//Deal this Condition as Hint(Purple Colour Font) [Hint] Please Continue Your Input
						cout<<"Line"<<i+1<<" --- "<<"cng ";
					//Line Above show the Pre-Set part of input,user will input the rest parameter in the follow procedure
					//cin function will deal the user's data when quit the werror handling loop
						//cin>>A[i].Point>>A[i].Score;
						break;}
						delete q;//Dynamic Memory Assignment	 
					}
					//	cout<<"DATAChange"<<endl;	//This Line act like as a symbol for the specific code
						cout<<"Please Input the line Number of the Data you want to change:Line ";
						cin>>LN;
						LN--;
						if(LN<i){
						cout<<Choose[0]<<" -- "<<Choise[0]<<endl;
						cout<<Choose[1]<<" -- "<<Choise[1]<<endl;
						cout<<Choose[2]<<" -- "<<Choise[2]<<endl;
						cout<<"Which Data do you want to Change,Please Enter the number:";
						cin>>*CAT;
						ChangeIdentify(*CAT,&(StuScr[LN]));
						ChangeFeedBack(&(StuScr[LN]),&i);
					//	delete CAT;	//Free Memory
						//DataChange Procedure
						cout<<"Line"<<i+1<<" --- ";
						cin>>StuScr[i].SubjectName;
						}else{
						SetColour((int)ErrorSet.FrontColour,(int)ErrorSet.BackColour);
						cout<<"[Error]Index OVERSTEP";
						SetColour((int)YEL,(int)Default.BackColour);
						cout<<" "<<"Not Allowed to change the data OVERSTEP,Please Input again!"<<endl;
						}
				}while(stricmp(StuScr[i].SubjectName ,"change")==0||stricmp(StuScr[i].SubjectName,"cng")==0);
				delete CAT;	//Free Memory
			}else{
				cout<<"Please Input again!(No Memory for input)"<<endl;
				cout<<"Line"<<i+1<<" --- "<<StuScr[i].SubjectName<<" ";
			}
		}
//		delete [] buf;//Dynamic Memeory Assignment
		cin>>StuScr[i].Point>>StuScr[i].Score>>StuScr[i].GPA;
		if(StuScr[i].GPA==1||StuScr[i].GPAOrNot==true){
		//the condition StuScr[i].GPAOrNot==true is add to ensure the Correct SumScr Calculation
		StuScr[i].GPAOrNot=1; 
		SumScr=SumScr+StuScr[i].Point;
		}
				
		Sleep(500);		//delay 0.5s
		if(i<Subject-1){	//prompt classify
		cout<<prompt[2]<<endl;	//Data Receive Prompt
		}else{
		cout<<prompt[3]<<endl;	//The Very last Line 
		}
	}//End Data-Input Procedure
	//All Data review + user confirm all right
//DataCheck Result Output
		cout<<endl<<"--- Data-Check Result ---"<<endl;
		for(i=0;i<Subject;i++){
			StuScr[i].StatusCode=CheckResult(&(StuScr[i]));
			WerrorDisplay(StuScr[i].StatusCode,&(StuScr[i]),i);
		}
		cout<<endl<<endl;
//Error Change
	for(i=0;i<Subject;i++){
		while((StuScr[i].StatusCode&0x0F)!=0x08){
			int LineCheck;
			cout<<"Please Input the line that you want to Change:Line ";
			cin>>LineCheck;
			if(StuScr[LineCheck].StatusCode==0x01){
				float newscr;
				SetColour((int)YEL,(int)Default.BackColour);
				cout<<"[Hint] This Line DataSet Have Score Error\n";
				SetWerrColour(DFT);
				cout<<"Please INPUT your NEW Correct Score For Correction:";
				cin>>newscr;
				do{
					StuScr[LineCheck].StatusCode=(&(StuScr[LineCheck]));
					if(StuScr[LineCheck].StatusCode=0x01){
					cout<<"[Hint] Still ERROR Score Input\n";
					cout<<"Please Input Again:";
					cin>>newscr;
					}
				}while(StuScr[LineCheck].StatusCode==0x01);
				ChangeData(&(StuScr[LineCheck]),StuScr[LineCheck].Point,newscr,StuScr[LineCheck].GPAOrNot); 
			}else if(StuScr[LineCheck].StatusCode==0x04){
				float newpnt;
				SetColour((int)YEL,(int)Default.BackColour);
				cout<<"[Hint] This Line DataSet Have Point Error\n";
				SetWerrColour(DFT);
				cout<<"Please INPUT your NEW Correct Point For Correction:";
				cin>>newpnt;
				do{
					StuScr[LineChcek].StatusCode=CheckResult(&(StuScr[LineCheck]));
					if(StuScr[LineCheck].StatusCode=0x04){
					cout<<"[Hint] Still ERROR Point Input\n";
					cout<<"Please Input Again:";
					cin>>newpnt;
					}
				}while(StuScr[LineCheck].StatusCode==0x04);
				ChangeData(&(StuScr[LineCheck]),newpnt,StuScr[LineCheck].Score,StuScr[LineCheck].GPAOrNot);
			}
			StuScr[LineCheck].StatusCode=CheckResult(&(StuScr[LineCheck]));
		}
	}		 
//GPA Calculate Procedure
	for(i=0;i<Subject;i++){
		CalCore(StuScr[i].Point,StuScr[i].Score,StuScr[i].GPAOrNot,SumScr);
		Sleep(50);
	} 
//Result Output Show-Out
	cout<<"----GPA RESULT----";
	cout<<prompt[4]<<endl;
	cout<<"Your GPA Is---"<<GPACal<<endl;
	cout<<"Your Total Point---"<<SumScr<<endl;
//End of the Programme
	cout<<prompt[5]<<endl;
	return 0;
} 
void PromptInit(void){
	//Almost Interface Costom-InterAction Prompt Initialize in this Function 
	strcpy(prompt[0],"Score Caculator");
	strcpy(prompt[1],"Please Input the Ammount of Subject for Calculate Below:");
	strcpy(prompt[2],"Your Data has Received,Please Continue input your Data Below");
	strcpy(prompt[3],"All your Data has received.Please Wait for calculate...");
	strcpy(prompt[4],"Your GPA Data calculate completed.Results are below");
	strcpy(prompt[5],"GPA Calculation Finished. Thanks for using the Score Calculator");
	strcpy(DataTemplate[0],"Please Input Your Data in Template given below");
	strcpy(DataTemplate[1],"<SubjectName> (space) <Point of the Subject> (space) <Score of the Subject> (space) ");
	strcpy(DataTemplate[2],"<Whether the Subject should be calculated in GPA>(1 represent for Yes,0 represent for No)");
	return;
} 
void CalCore(float Point,float Score,bool GPAOrNot,float SumScr){
	float buffer;
	buffer=Point*Score*GPAOrNot;
	buffer/=SumScr;
	GPACal+=buffer;
	return;
}
void ErrorPromptInit(void){
//
	strcpy(Error[0],"KeyWord Conflict. Please Change SubjectName that you had input.");
	strcpy(Error[1],"Too MUCH Data. Please Input youe Data again.");
	strcpy(Error[2],"Too LESS Data. Please Input MORE Data For GPA Calculation");
	return; 
} 
void WarningPromptInit(void){
	strcpy(Warning[0],""); 
	return;
}
void ChangeIdentify(int ChangeId,ScoreData* cng){
	float*C=new float;
	bool* D=new bool;
	if(ChangeId==0){//Id==0<=>Change Point of the Subject
	cout<<"Input Your Point For Change:";
	cin>>*C;
	if(cng->GPAOrNot==1){
	SumScr-=cng->Point;
	SumScr+=*C;
	}
	//SumScr synchronise change,fix the bug that didn't change the Critical Calculate Vary
	//leading to the wrong GPA Calculate Result  
	ChangeData(cng,*C,cng->Score,cng->GPAOrNot);
	}else if(ChangeId==1){
	cout<<"Input Your Score For Change:";
	cin>>*C;
	ChangeData(cng,(cng->Point),*C,(cng->GPAOrNot));
	}else{
	cout<<"Input Your Validity For Change:";
	cin>>*D;
	if(cng->GPAOrNot==1&&*D==0){
	SumScr-=cng->Point;
	}else if(cng->GPAOrNot==0&&*D==1){
	SumScr+=cng->Point;
	}
	//Ensure that when GPAValidity 1->0,SumScr is right
	ChangeData(cng,(cng->Point),(cng->Score),*D);	
	}
	delete C;
	delete D;
	return;
}
void ChangeData(ScoreData* cng,float Pnt,float Scr,bool Validity){
	cng->Point =Pnt;
	cng->Score =Scr;
	cng->GPAOrNot =Validity;
	return;
}
void ChangeFeedBack(ScoreData* cng,int* NowLine){
	cout<<"Your Change have received,Please Check"<<endl;
	cout<<"Subject Name  "<<"Point  "<<"Score  "<<"GPA(1:=Yes,0:=No)"<<endl;
	cout<<left<<setw(strlen("Subject Name  "))<<cng->SubjectName;
	cout<<left<<setw(strlen("Point  "))<<cng->Point;
	cout<<left<<setw(strlen("Score  "))<<cng->Score;
	cout<<left<<setw(strlen("GPA(1:=Yes,0:=No)"))<<cng->GPAOrNot<<endl;
	cout<<"Continue for Data-Input"<<endl;
	return; 
}
